<?php
require_once 'Croese/Google/Chart/Encoding.php';
/**
 * Extended encoding
 * -----------------
 * 
 * Specify extended encoding with
 * chd=e:<chart data string>
 * Where <chart data string> contains pairs of the characters: A to Z, a to z, 
 * 0 to 9, hyphen (-), period (.), underscore (_), and comma (,) as a separator.
 * 
 * Note:
 * - AA = 0, AZ = 25, Aa = 26, Az = 51, A0 = 52, A9 = 61, A- = 62, A. = 63
 *   BA = 64, BZ = 89, Ba = 90, Bz = 115, B0 = 116, B9 = 125, B- = 126, B. = 127
 *   .A = 4032, .Z = 4057, .a = 4058, .z = 4083, .0 = 4084, .9 = 4093, .- = 4094, .. = 4095.
 * - Specify a missing value with two underscore (__) characters.
 * - If you have more than one set of data, separate each set with a comma (,).
 */
class Croese_Google_Chart_Encoding_Extended implements Croese_Google_Chart_Encoding
{
	
	const VALUE_MIN = 0;
	const VALUE_MAX = 4095;
	const VALUE_MISSING = '__'; 

	protected $_simpleEncoding = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
	
	/**
	 * Met deze functie encoden we de data op de Extended manier.
	 *
	 * @param array $data
	 */
	public function encode($data)
	{
		$values = array();
		if(is_array($data) && !empty($data))
		{
			foreach ($data as $dataElement)
			{
				// multiple datasets
				if (is_array($dataElement))
				{
					$dataSet = $dataElement;
					foreach ($dataSet as $dataElem)
					{
						$dataElem = $this->validateElement($dataElem);		
					}
				}
				else
				{
					$dataElement = $this->validateElement($dataElement);
					$values[] = $this->_berekenExtendedResult($dataElement);	
				}
			}
			return 'chd=e:' . implode(',', $values);
		}
		else
		{
			throw new Exception('Geen data opgegeven');
			return '';
		}
	}

	/**
	 * Met deze functie zetten we een decimale waarde om naar een string ter
	 * grootte van twee karakters
	 *
	 * @param int $value
	 * @return string
	 */
	private function _berekenExtendedResult($value)
	{
		global $keys;
		
		$first = $value  >> 6;
		$second = $value & 0x3F; // binaire waarde 111111;
		return $keys[$first] . $keys[$second];
	}

	/**
	 * Valideert de data. Wanneer de data niet valide is geven we een
	 * 'missing value' terug
	 *
	 * @param int $element
	 * @return string
	 */
	private function validateElement($element)
	{
		if(is_float((float)$element) || is_int((int)$element))
		{
			if($element >= self::VALUE_MIN && $element <= self::VALUE_MAX)
			{
				return $element;	
			}
			else
			{
				throw new Exception(sprintf("Waarde '%s' moet mag niet kleiner zijn dan 0.0 en niet groter dan 100.0", $element));
				return self::VALUE_MISSING;
			}
		}
		else
		{
			throw new Exception(sprintf("Waarde '%s' moet wel een float of int zijn", $element));
			return self::VALUE_MISSING;
		}
	}	
}